package cn.ycq.im.commons.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yuchaoqun
 * @email chaoqunyu9311@163.com
 * @date 2021.03.15 20:13
 */
public class QrCodeHelper {
    public static final QrCodeHelper DEFAULT = new QrCodeHelper();


    private final Map<EncodeHintType, Object> hints;
    private final int size;

    public QrCodeHelper() {
        this(300);
    }

    public QrCodeHelper(int size) {
        hints = new ConcurrentHashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 1);

        this.size = size;
    }

    public static void writeTo(RenderedImage sourceImage, OutputStream outputStream) throws IOException {
        ImageIO.write(sourceImage, "PNG", outputStream);
    }

    public static byte[] writeToBytes(RenderedImage sourceImage) throws WriterException, IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        writeTo(sourceImage, outputStream);
        return outputStream.toByteArray();
    }

    public BufferedImage createImage(String content) throws WriterException {
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                BarcodeFormat.QR_CODE, size, size, hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000
                        : 0xFFFFFFFF);
            }
        }
        return image;
    }

    public BufferedImage createImageWithLogo(String content, InputStream logoDataStream, int logoWidth, int logoHeight) throws Exception {
        BufferedImage sourceImage = createImage(content);

        BufferedImage logo = ImageIO.read(logoDataStream);
        int width = logo.getWidth();
        int height = logo.getHeight();
        if (width > logoWidth) {
            width = logoWidth;
        }
        if (height > logoHeight) {
            height = logoHeight;
        }

        Image instance = logo.getScaledInstance(width, height, Image.SCALE_SMOOTH);

        // 将二维码的logo增加padding值
        BufferedImage bufferedImage = new BufferedImage(width, width, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = bufferedImage.getGraphics();
        graphics.drawImage(instance,0,0,null);

        // 画logo到二维码中间位置
        Graphics graphics1 = sourceImage.getGraphics();
        int x = (this.size - width) / 2;
        int y = (this.size - height) / 2;
        graphics1.drawImage(bufferedImage, x, y, null);

        sourceImage.flush();
        return sourceImage;
    }

}
